package cn.abcsys.devops.client.core;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.Closeable;
import java.io.IOException;

import cn.abcsys.devops.client.api.DockerClient;
import cn.abcsys.devops.client.api.command.DockerCmdExecFactory;
import cn.abcsys.devops.client.api.command.InfoCmd;
import cn.abcsys.devops.client.core.command.InfoCmdImpl;

/**
 * @author Konstantin Pelykh (kpelykh@gmail.com)
 * @see "https://github.com/docker/docker/blob/master/api/client/commands.go"
 */
public class DockerClientImpl implements Closeable, DockerClient {

    private final DockerClientConfig dockerClientConfig;

    private DockerCmdExecFactory dockerCmdExecFactory;

    private DockerClientImpl() {
        this(DefaultDockerClientConfig.createDefaultConfigBuilder().build());
    }

    private DockerClientImpl(String serverUrl) {
        this(configWithServerUrl(serverUrl));
    }

    private DockerClientImpl(DockerClientConfig dockerClientConfig) {
        checkNotNull(dockerClientConfig, "config was not specified");
        this.dockerClientConfig = dockerClientConfig;
    }

    private static DockerClientConfig configWithServerUrl(String serverUrl) {
        return DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost(serverUrl).build();
    }

    public static DockerClientImpl getInstance() {
        return new DockerClientImpl();
    }

    public static DockerClientImpl getInstance(DockerClientConfig dockerClientConfig) {
        return new DockerClientImpl(dockerClientConfig);
    }

    public static DockerClientImpl getInstance(String serverUrl) {
        return new DockerClientImpl(serverUrl);
    }

    public DockerClientImpl withDockerCmdExecFactory(DockerCmdExecFactory dockerCmdExecFactory) {
        checkNotNull(dockerCmdExecFactory, "dockerCmdExecFactory was not specified");
        this.dockerCmdExecFactory = dockerCmdExecFactory;
        this.dockerCmdExecFactory.init(dockerClientConfig);
        return this;
    }

    private DockerCmdExecFactory getDockerCmdExecFactory() {
        checkNotNull(dockerCmdExecFactory, "dockerCmdExecFactory was not specified");
        return dockerCmdExecFactory;
    }

    /**
     * * MISC API *
     */

    @Override
    public InfoCmd infoCmd() {
        return new InfoCmdImpl(getDockerCmdExecFactory().createInfoCmdExec());
    }

    @Override
    public void close() throws IOException {
        getDockerCmdExecFactory().close();
    }

}
